#!/system/bin/python

import os
import math
import sys
import shlex, subprocess

from pyecharts import options as opts
from pyecharts.charts.basic_charts.graph import Graph

if len(sys.argv) == 1:
    top_dir = "."
else:
    top_dir = sys.argv[1]

def show_files(path, all_files):
    file_list = os.listdir(path)
    for file in file_list:
        cur_path = os.path.join(path, file)
        if os.path.isdir(cur_path):
            show_files(cur_path, all_files)
        else:
            all_files.append(path+ "/" + file)

    return all_files

cwd = os.getcwd()
os.chdir(top_dir)

nodes = []
links = []

nodedict = {}
linklist = []
nodesizedict = {}

def get_all_size(fr, size, alllink, allnode):
    for (f,t) in alllink:
        if fr == f:
            size += allnode[t]
            return get_all_size(t, size, alllink, allnode)
    return size

contents = show_files(".", [])
for content in contents:
    #G.add_node(os.path.basename(content))
    if content.find("/ld-musl-") > 0:
        name = "libc.so"
    else:
        name = os.path.basename(content)
    nodedict[name] = int(os.path.getsize(content) / 1024)
    if nodedict[name] == 0:
        nodedict[name] = 1

for content in contents:
    proc = subprocess.Popen(['readelf','-Wd', content], stdout=subprocess.PIPE)
    out = proc.stdout.readlines()
    for o in out:
        l = o.decode().strip()
        if "Shared library" not in l:
            continue
        pos = l.find('[')
        need_so = l[pos+1:-1]
        if need_so in nodedict.keys():
            linklist.append((os.path.basename(content), need_so))

os.chdir(cwd)

for n,s in nodedict.items():
    nodes.append({ "name": n, "symbolSize": int(math.log1p(s)) })
    size = get_all_size(n, 0, linklist, nodedict)
    nodesizedict[n] = size

for (fr,to) in linklist:
    links.append(opts.GraphLink(source=fr, target=to, value=nodesizedict[to]))

graph = Graph(init_opts=opts.InitOpts(width="3000px",
                                height="1800px",
                                page_title="so link"
                                ))
graph.add("", nodes, links, edge_symbol=['circle', 'arrow'],
    repulsion=80,
    edge_label=opts.LabelOpts(
            is_show=True, position="middle", formatter="{c} KB"),
    layout="circular",
    is_rotate_label=True,
    linestyle_opts=opts.LineStyleOpts(color="source", curve=0.3),
    label_opts=opts.LabelOpts(position="right"))
graph.render("lib_graph.html")
